package org.dromara.wms.service;

import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.dromara.common.web.core.BaseService;
import org.dromara.wms.domain.*;
import org.springframework.stereotype.Service;
import org.dromara.wms.mapper.WmsScheduleLineMapper;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * 生产计划排程Service业务层处理
 *
 * @author wenrui Su
 * @date 2024-05-05
 */
@RequiredArgsConstructor
@Service
public class WmsScheduleLineService extends BaseService {

    private final WmsScheduleLineMapper baseMapper;
    private final WmsTaskService wmsTaskService;
    private final WmsWorkshopService workshopService;
    private final WmsStockService stockService;
    private final WmsProductServiceImpl wmsProductService;
    private final WmsOrderServiceImpl wmsOrderService;

    /**
     * 查询生产计划排程
     */
    public WmsScheduleLine queryById(Long lineId){
        return baseMapper.getScheduleLine(lineId);
    }

    /**
     * 查询生产计划排程列表
     */
    public TableDataInfo<WmsScheduleLine> queryPageList(WmsScheduleLine bo, PageQuery pageQuery) {
        Page<WmsScheduleLine> result = baseMapper.getScheduleLine2(pageQuery.build(), bo);
        return TableDataInfo.build(result);
    }

    /**
     * 查询生产计划排程列表
     */
    public List<WmsScheduleLine> queryList(WmsScheduleLine bo) {
        LambdaQueryWrapper<WmsScheduleLine> lqw = buildQueryWrapper(bo);
        return baseMapper.selectList(lqw);
    }

    private LambdaQueryWrapper<WmsScheduleLine> buildQueryWrapper(WmsScheduleLine bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<WmsScheduleLine> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getId() != null, WmsScheduleLine::getId, bo.getId());
        lqw.eq(bo.getWorkshopId() != null, WmsScheduleLine::getWorkshopId, bo.getWorkshopId());
        lqw.eq(bo.getProductId() != null, WmsScheduleLine::getProductId, bo.getProductId());
        lqw.eq(bo.getStartTime() != null, WmsScheduleLine::getStartTime, bo.getStartTime());
        lqw.eq(bo.getEndTime() != null, WmsScheduleLine::getEndTime, bo.getEndTime());
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), WmsScheduleLine::getStatus, bo.getStatus());
        return lqw;
    }

    /**
     * 新增生产计划排程
     */
    public Boolean insertByBo(WmsScheduleLine bo) {
        validEntityBeforeSave(bo);
        boolean flag = baseMapper.insert(bo) > 0;
        return flag;
    }

    /**
     * 修改生产计划排程
     */
    @Transactional(propagation = Propagation.REQUIRED)
    public Boolean updateByBo(WmsScheduleLine bo) throws WmsStockService.emptyException {
        validEntityBeforeSave(bo);
        if (Objects.equals(bo.getStatus(), "1")){
          //batchCode按';'分割
          String[] batchCodeList = bo.getBatchCode().split(";");
          if (bo.getQuantity() % batchCodeList.length > 0){
            throw new WmsStockService.emptyException(bo.getQuantity() + "个需求数量无法平均分配给" + batchCodeList.length + "个工单，请修改后重试！");
          }
          bo.setQuantity(bo.getQuantity() / batchCodeList.length);

          //判断流水线仓库库存是否足够
          //获取所需物料清单
          WmsTask wmsTaskForBomMaterial = new WmsTask();
          wmsTaskForBomMaterial.setQuantity(bo.getQuantity() * batchCodeList.length);
          wmsTaskForBomMaterial.setScheduleLineId(bo.getLineId());
          List<WmsBomLine> BottomMaterial = wmsTaskService.getBomList(wmsTaskForBomMaterial);
          //获取流水线库存
          WmsWorkshop workshop = workshopService.queryById(bo.getWorkshopId());
          if (workshop.getWhId() == null){
            throw new WmsStockService.emptyException(bo.getWorkshopName()+" 未绑定仓库，请前往绑定仓库后重新排程");
          }
          WmsStock wmsStock = new WmsStock();
          wmsStock.setWarehouseId(workshop.getWhId());
          List<WmsOrderLine> orderLines = new ArrayList<>();
          for (WmsBomLine wmsBomLine : BottomMaterial) {
            wmsStock.setProductId(wmsBomLine.getProductId());
            wmsStock.setBatchCode(bo.getBatchCode());
            List<WmsStock> wmsStockList = stockService.queryList(wmsStock);
            double quantitySum = wmsStockList.stream().mapToDouble(WmsStock::getQuantity).sum();
            if (quantitySum - Double.parseDouble(wmsBomLine.getQuantity()) < 0) {
              //当前材料库存不足
              WmsOrderLine wmsOrderLine = new WmsOrderLine();
              wmsOrderLine.setProductId(wmsBomLine.getProductId());
              wmsOrderLine.setPrice(wmsBomLine.getPurchasePrice());
              wmsOrderLine.setQuantity(Double.parseDouble(wmsBomLine.getQuantity()) - quantitySum);
              wmsOrderLine.setMeasureUnit(wmsProductService.queryById(wmsBomLine.getProductId()).getMeasureUnit());
              wmsOrderLine.setBatchCode(bo.getBatchCode());
              wmsOrderLine.setTotalMoney(wmsBomLine.getPurchasePrice() * wmsOrderLine.getQuantity());
              wmsOrderLine.setCostMoney(wmsBomLine.getPurchasePrice() *wmsOrderLine.getQuantity());
              orderLines.add(wmsOrderLine);
            }
          }
          if(!orderLines.isEmpty()){
            WmsOrder wmsOrder = new WmsOrder();
            wmsOrder.setName("工单表生产需求单");
            wmsOrder.setTypeId(21L);
            wmsOrder.setSelfWhId(wmsStock.getWarehouseId());
            wmsOrder.setStatus("1");
            wmsOrder.setLine(orderLines);
            wmsOrder.setSourceId(bo.getLineId());
            wmsOrder.setRemark("工单表 "+bo.getLineId()+" 生产需求订单");
            wmsOrderService.insertByBo(wmsOrder);
          }
          for (String batchCode : batchCodeList) {
            //排程 生成相应工单
            WmsTask wmsTask = new WmsTask();
            wmsTask.setTaskName("工单表 "+bo.getLineId());
            wmsTask.setScheduleLineId(bo.getLineId());
            WmsTask resData = wmsTaskService.querySort();
            if (resData != null) wmsTask.setSort((resData.getSort() != null)?resData.getSort()+1L:1L);
            else wmsTask.setSort(0L);
            wmsTask.setProductId(bo.getProductId());
            if(batchCode == null || Objects.equals(batchCode,"")){
              batchCode = "0";
            }
            wmsTask.setBatchCode(batchCode);
            wmsTask.setStartTime(bo.getStartTime());
            wmsTask.setEndTime(bo.getEndTime());
            wmsTask.setCreateBy(bo.getCreateBy());
            wmsTask.setStatus("0");
            wmsTask.setCreateBy(bo.getCreateBy());
            wmsTask.setCreateTime(new Date());
            wmsTask.setBomId(bo.getBomId());
            wmsTask.setQuantity(bo.getQuantity());
            wmsTaskService.insertByBo(wmsTask);

            //排程后，工单自动派工
            wmsTask.setStatus("1");
            wmsTaskService.updateByBo(wmsTask);
          }
          bo.setQuantity(bo.getQuantity() * batchCodeList.length);
        }
        return baseMapper.updateById(bo) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(WmsScheduleLine entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除生产计划排程
     */
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        wmsTaskService.deleteWithValidByIds(ids,isValid);
        return baseMapper.deleteBatchIds(ids) > 0;
    }
}
